import type * as React from "react";
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetFooter,
  SheetTrigger,
  SheetClose,
} from "../../shad/components/ui/sheet";
import { cn } from "@humansignal/shad/utils";
import { cnm } from "../../utils/utils";

export interface DrawerProps {
  /**
   * Whether the drawer is open
   */
  open?: boolean;
  /**
   * Callback when the drawer open state changes
   */
  onOpenChange?: (open: boolean) => void;
  /**
   * Side from which the drawer slides in
   * @default "right"
   */
  side?: "top" | "right" | "bottom" | "left";
  /**
   * Drawer title
   * If not provided, a hidden "Drawer" title will be rendered for accessibility
   */
  title?: React.ReactNode;
  /**
   * Drawer description
   */
  description?: React.ReactNode;
  /**
   * Footer content (e.g., action buttons)
   */
  footer?: React.ReactNode;
  /**
   * Main content of the drawer
   */
  children: React.ReactNode;
  /**
   * Additional CSS classes for the drawer content
   */
  className?: string;
  /**
   * Additional CSS classes for the drawer header
   */
  headerClassName?: string;
  /**
   * Additional CSS classes for the drawer footer
   */
  footerClassName?: string;
  /**
   * Additional CSS classes for the drawer body wrapper
   */
  bodyClassName?: string;
  /**
   * Whether to show the close button
   * @default true
   */
  showCloseButton?: boolean;
  /**
   * Whether to close the drawer when clicking outside (on the overlay)
   * @default true
   */
  closeOnClickOutside?: boolean;
  /**
   * Custom CSS classes for the SheetContent wrapper
   * This allows full control over the drawer content container styling
   * For left/right sides, default width is "w-1/4" if not specified
   */
  contentClassName?: string;
  /**
   * Custom data-testid for the drawer content
   * @default "drawer"
   */
  dataTestId?: string;
}

/**
 * Drawer component
 *
 * A slide-out panel component that appears from the edge of the screen.
 * Built on top of Radix UI Dialog primitives and styled with Tailwind CSS.
 *
 * @example
 * ```tsx
 * <Drawer
 *   open={isOpen}
 *   onOpenChange={setIsOpen}
 *   title="User Details"
 *   description="View and edit user information"
 * >
 *   <div>Content here</div>
 * </Drawer>
 * ```
 */
export const Drawer = ({
  open,
  onOpenChange,
  side = "right",
  title,
  description,
  footer,
  children,
  className,
  headerClassName,
  footerClassName,
  bodyClassName,
  showCloseButton = true,
  closeOnClickOutside = true,
  contentClassName,
  dataTestId = "drawer",
}: DrawerProps) => {
  const defaultWidth = side === "left" || side === "right" ? "w-1/4" : undefined;
  const computedContentClassName = cnm(
    // Apply default width for left/right sides if contentClassName is not provided
    contentClassName ? undefined : defaultWidth,
    contentClassName, // This can override default width via twMerge
    className,
  );

  return (
    <Sheet open={open} onOpenChange={onOpenChange} modal={true}>
      <SheetContent
        side={side}
        className={computedContentClassName}
        showCloseButton={closeOnClickOutside === false ? true : showCloseButton}
        closeOnClickOutside={closeOnClickOutside}
        data-slot="drawer-content"
        data-testid={dataTestId}
      >
        <SheetHeader
          className={cn(
            "p-base border-b border-neutral-border",
            headerClassName,
            !title && !description ? "sr-only !m-0 !p-0 !space-y-0 h-0 overflow-hidden" : undefined,
          )}
          data-slot="drawer-header"
          data-testid="drawer-header"
        >
          <SheetTitle data-slot="drawer-title" data-testid="drawer-title" className={cn(!title && "sr-only")}>
            {title || "Drawer"}
          </SheetTitle>
          {description && (
            <SheetDescription data-slot="drawer-description" data-testid="drawer-description">
              {description}
            </SheetDescription>
          )}
        </SheetHeader>
        <div
          className={cn("flex-1 min-h-0 overflow-y-auto", bodyClassName)}
          data-slot="drawer-body"
          data-testid="drawer-body"
        >
          {children}
        </div>
        {footer && (
          <SheetFooter
            className={cn("p-base border-t border-neutral-border", footerClassName)}
            data-slot="drawer-footer"
            data-testid="drawer-footer"
          >
            {footer}
          </SheetFooter>
        )}
      </SheetContent>
    </Sheet>
  );
};

export { SheetTrigger as DrawerTrigger, SheetClose as DrawerClose, Sheet };
